#include "Shell.h"


Shell::Shell() {
	tokens = new vector<Token*>();
	currentRule = new Rule();
	newLine = true;
	running = true;
	hasInput = false;
	ifs.open("test.sh");
	ofs.open("log.txt");}

Shell::~Shell() {

}


void Shell::run(){
	while(running){
		if(newLine){
			cout << "Terrorshell>";
			newLine = false;
			parseTokens();
			//execute parsed commands

			//delete parsed commands

		}
	}
}

void Shell::parseTokens(){
	// kies een actie
	bool isInputCommand = false;
	bool isOutputCommand = false;
	bool isAppendCommand = false;
	bool isBackgroundProcess = false;
	hasInput = true;


	Token * tp;
	Rule * currentRule = new Rule();
	Command * currentCommand = 0;

	while(hasInput){
		tp = nextToken(cin);
	//	cout <<"shell::parseTokens: token text: " << tp->getText() << " type: " << tp->getType() << endl;
		switch (tp->getType()) {
		case Token::END:
			currentRule->executeCommands();
			hasInput = false;
			newLine = true;
			//todo: delete remaining objects
			break;
		case Token::EOL:
			currentRule->executeCommands();
			newLine = true;
			hasInput = false;
			break;
		case Token::SEQUENCE: // ;
			break;
		case Token::PIPE: // |
			currentRule->addPipe();
			break;
		case Token::INPUT: // <
			isInputCommand = true; // pass next token as arg to last command
			break;
		case Token::OUTPUT: // >
			isOutputCommand = true; // last command was input, next is output
			break;
		case Token::APPEND: // >>
			isAppendCommand = true; // last command was input, next is output
			currentCommand->setIsAppend();
			break;
		case Token::WORD: // anything that hasnt been caught yet
			if(isInputCommand){ // if previous token was <
				currentCommand->setInputFile(tp->getText());
			} else if (isOutputCommand){ // if previous token was >
				currentCommand->setOutputFile(tp->getText());
			} else if (isAppendCommand){ // if previous token was >>
				currentCommand->setOutputFile(tp->getText());
			} else if (isBackgroundProcess) { // if previous token was &
				//TODO: implement this
			} else if(currentCommand == 0){

					if(tp->getText().compare("exit") == 0){
						running = false;
						hasInput = false;
						//TODO: clean up rule object here
						break;
					} else {
						//TODO: addmore cases here
						currentCommand = new Command(tp->getText());
						currentRule->addCommand(currentCommand);
					}
			} else {
				currentCommand->addArgument(tp->getText());
			}
			break;

#if	SH_LEVEL >= 1	// versatile
		case Token::BACKGROUND: // &
			isBackgroundProcess = true;
			break;
#endif

#if	SH_LEVEL >= 2	// advanced
		case Token::AND:
			ofs << "&&";
			break;
		case Token::OR:
			ofs << "||";
			break;
		case Token::SUBS:
			ofs << "(";
			break;
		case Token::ENDS:
			ofs << ")";
			break;
		case Token::VAR:
			ofs << "VAR=|" << tp->getText() << "|";
			break;
		case Token::EXPR:
			ofs << "EXPR=|" << tp->getText() << "|";
			break;
#endif

#if	SH_LEVEL >= 3 	// sh script
		case Token::BQUOTE:
			ofs << "`";
			break;
		case Token::HERE:
			ofs << "<<";
			break;
		case Token::BREAK:
			ofs << ";;";
			break;
#endif

#if	SH_LEVEL >= 4	// ksh/bash
		case Token::EVAL:
			ofs << "$(";
			break;
#endif

		default:	// missed something ?
			ofs << "?"<< tp->getText() << "?"; break;
		}
	}
}


